package com.starsea.book

import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.os.Build
import com.alipay.sdk.app.AlipayApi
import com.blankj.utilcode.util.LogUtils
import com.bytedance.sdk.openadsdk.TTAdConfig
import com.bytedance.sdk.openadsdk.TTAdConstant
import com.bytedance.sdk.openadsdk.TTAdSdk
import com.github.liuyueyi.quick.transfer.ChineseUtils
import com.github.liuyueyi.quick.transfer.constants.TransType
import com.jeremyliao.liveeventbus.LiveEventBus
import com.scwang.smart.refresh.footer.ClassicsFooter
import com.scwang.smart.refresh.header.ClassicsHeader
import com.scwang.smart.refresh.layout.SmartRefreshLayout
import com.starsea.book.base.AppContextWrapper
import com.starsea.book.constant.AppConst.channelIdDownload
import com.starsea.book.constant.AppConst.channelIdReadAloud
import com.starsea.book.constant.AppConst.channelIdWeb
import com.starsea.book.constant.PreferKey
import com.starsea.book.data.appDb
import com.starsea.book.help.AppWebDav
import com.starsea.book.help.CrashHandler
import com.starsea.book.help.DefaultData
import com.starsea.book.help.LifecycleHelp
import com.starsea.book.help.RuleBigDataHelp
import com.starsea.book.help.book.BookHelp
import com.starsea.book.help.config.AppConfig
import com.starsea.book.help.config.ThemeConfig.applyDayNight
import com.starsea.book.help.coroutine.Coroutine
import com.starsea.book.help.http.Cronet
import com.starsea.book.help.http.ObsoleteUrlFactory
import com.starsea.book.help.http.okHttpClient
import com.starsea.book.help.source.SourceHelp
import com.starsea.book.help.storage.Backup
import com.starsea.book.model.BookCover
import com.starsea.book.utils.defaultSharedPreferences
import com.starsea.book.utils.getPrefBoolean
import com.starsea.book.R
import kotlinx.coroutines.launch
import splitties.init.appCtx
import splitties.systemservices.notificationManager
import java.net.URL
import java.util.concurrent.TimeUnit

class App : Application() {

    private lateinit var oldConfig: Configuration

    override fun onCreate() {
        super.onCreate()
    }

    fun initApp() {
        AlipayApi.registerApp(this, "2021004135676988")
        oldConfig = Configuration(resources.configuration)
        CrashHandler(this)
        //预下载Cronet so
        Cronet.preDownload()
        createNotificationChannels()
        applyDayNight(this)
        LiveEventBus.config()
            .lifecycleObserverAlwaysActive(true)
            .autoClear(false)
        registerActivityLifecycleCallbacks(LifecycleHelp)
        defaultSharedPreferences.registerOnSharedPreferenceChangeListener(AppConfig)
        DefaultData.upVersion()
        Coroutine.async {
            launch { installGmsTlsProvider(appCtx) }
            //初始化封面
            BookCover.toString()
            //清除过期数据
            appDb.cacheDao.clearDeadline(System.currentTimeMillis())
            if (getPrefBoolean(PreferKey.autoClearExpired, true)) {
                val clearTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1)
                appDb.searchBookDao.clearExpired(clearTime)
            }
            RuleBigDataHelp.clearInvalid()
            BookHelp.clearInvalidCache()
            Backup.clearCache()
            //初始化简繁转换引擎
            when (AppConfig.chineseConverterType) {
                1 -> ChineseUtils.preLoad(true, TransType.TRADITIONAL_TO_SIMPLE)
                2 -> ChineseUtils.preLoad(true, TransType.SIMPLE_TO_TRADITIONAL)
            }
            //调整排序序号
            SourceHelp.adjustSortNumber()
            //同步阅读记录
            if (AppConfig.syncBookProgress) {
                AppWebDav.downloadAllBookProgress()
            }
            URL.setURLStreamHandlerFactory(ObsoleteUrlFactory(okHttpClient))
        }

        TTAdSdk.init(
            this,
            TTAdConfig.Builder()
                .appId("5488153")
                .appName("星海小说")
                .directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI)
                .build()
        )

        TTAdSdk.start(object : TTAdSdk.Callback {
            override fun success() {
            }

            override fun fail(p0: Int, p1: String?) {
                LogUtils.e(">>>> init p0 = ${p0} \n p1 = ${p1}")
            }

        })
//        星海小说_激励视频代码位 ： 956204408

        //强烈建议在应用对应的Application#onCreate()方法中调用，避免出现content为null的异常
//        TTAdSdk.init(context,
//            new TTAdConfig.Builder()
//                .appId("xxxxxxx")//xxxxxxx为穿山甲媒体平台注册的应用ID
//                .useTextureView(true) //默认使用SurfaceView播放视频广告,当有SurfaceView冲突的场景，可以使用TextureView
//                .appName("APP测试媒体")
//                .titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK)//落地页主题
//                .allowShowNotify(true) //是否允许sdk展示通知栏提示,若设置为false则会导致通知栏不显示下载进度，存在违规风险，请勿随意更改
//                .debug(true) //测试阶段打开，可以通过日志排查问题，上线时去除该调用
//                .directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI) //允许直接下载的网络状态集合,没有设置的网络下点击下载apk会有二次确认弹窗，弹窗中会披露应用信息
//                .supportMultiProcess(false) //是否支持多进程，true支持
//            ~~ .asyncInit(true) //是否异步初始化sdk,设置为true可以减少SDK初始化耗时。3450版本开始废弃~~
//        //.httpStack(new MyOkStack3())//自定义网络库，demo中给出了okhttp3版本的样例，其余请自行开发或者咨询工作人员。
//        .updateAdConfig(ttAdConfig)//参数类型为TTAdConfig；注意使用该方法会覆盖之前初始化sdk的配置的data值；个性化推荐设置详见：https://www.csjplatform.com/supportcenter/26234
//            .build());
        //如果明确某个进程不会使用到广告SDK，可以只针对特定进程初始化广告SDK的content
        //if (PROCESS_NAME_XXXX.equals(processName)) {
        //   TTAdSdk.init(context, config);
        //}


    }

    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(AppContextWrapper.wrap(base))
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        val diff = newConfig.diff(oldConfig)
        if ((diff and ActivityInfo.CONFIG_UI_MODE) != 0) {
            applyDayNight(this)
        }
        oldConfig = Configuration(newConfig)
    }

    /**
     * 尝试在安装了GMS的设备上(GMS或者MicroG)使用GMS内置的Conscrypt
     * 作为首选JCE提供程序，而使Okhttp在低版本Android上
     * 能够启用TLSv1.3
     * https://f-droid.org/zh_Hans/2020/05/29/android-updates-and-tls-connections.html
     * https://developer.android.google.cn/reference/javax/net/ssl/SSLSocket
     *
     * @param context
     * @return
     */
    private fun installGmsTlsProvider(context: Context) {
        try {
            val gms = context.createPackageContext(
                "com.google.android.gms",
                CONTEXT_INCLUDE_CODE or CONTEXT_IGNORE_SECURITY
            )
            gms.classLoader
                .loadClass("com.google.android.gms.common.security.ProviderInstallerImpl")
                .getMethod("insertProvider", Context::class.java)
                .invoke(null, gms)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 创建通知ID
     */
    private fun createNotificationChannels() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
        val downloadChannel = NotificationChannel(
            channelIdDownload,
            getString(R.string.action_download),
            NotificationManager.IMPORTANCE_DEFAULT
        ).apply {
            enableLights(false)
            enableVibration(false)
            setSound(null, null)
            importance = NotificationManager.IMPORTANCE_LOW
        }

        val readAloudChannel = NotificationChannel(
            channelIdReadAloud,
            getString(R.string.read_aloud),
            NotificationManager.IMPORTANCE_DEFAULT
        ).apply {
            enableLights(false)
            enableVibration(false)
            setSound(null, null)
            importance = NotificationManager.IMPORTANCE_LOW
        }

        val webChannel = NotificationChannel(
            channelIdWeb,
            getString(R.string.web_service),
            NotificationManager.IMPORTANCE_DEFAULT
        ).apply {
            enableLights(false)
            enableVibration(false)
            setSound(null, null)
            importance = NotificationManager.IMPORTANCE_LOW
        }

        //向notification manager 提交channel
        notificationManager.createNotificationChannels(
            listOf(
                downloadChannel,
                readAloudChannel,
                webChannel
            )
        )
    }

    init {

        SmartRefreshLayout.setDefaultRefreshHeaderCreator { context, _ ->
            ClassicsHeader(context)
        }
        SmartRefreshLayout.setDefaultRefreshFooterCreator { context, _ -> ClassicsFooter(context) };
    }
}
